home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
MacWorld 1999 July
/
Macworld (1999-07).dmg
/
Shareware World
/
Info
/
For Developers
/
Mops 3.4.sea
/
Mops source
/
Toolbox classes
/
Dialog+
< prev
next >
Wrap
Text File
|
1998-12-19
|
8KB
|
348 lines
\ Dialog+ - MRH April 87.
\ This subclass of Dialog implements modeless dialogs, popup menu support,
\ and other things.
\ Nov 87 mrh Added enabling and disabling of dialogs.
\ July 91 mrh Migrated some methods to Dialog (now in a module).
\ Mar 95 mrh Event handlers no longer return a boolean
need dialog
syscall DialogSelect
syscall IsDialogEvent
syscall TEActivate
syscall TEDeactivate
syscall TrackGoAway
syscall TETextBox
objPtr DLG-CHAIN \ Head of chain of open dialogs. When
\ DialogSelect returns TRUE, we search this
\ chain to find which which one was hit.
objPtr ACTIVE_DLG
objPtr THIS_DLG \ These 3 objPtrs will be set to class Dialog+.
var DPTR clear: dptr
handle TEHDL
\ This is a copy of the textH field of a dialog, if a dialog window
\ is frontmost. Nil otherwise. This allows us to call TEidle in the
\ main event loop when necessary, as required for the insertion point
\ to blink.
handle SaveTEhdl \ Saves TEhdl while we're suspended
$ A0 constant TEXTH_OFFS
: SET_TEHDL \ ( wnd-ptr -- )
\ wnd-ptr is the (relative) address of the dialog's window,
\ which is the same as the address of the dialog record itself,
\ as the window field comes first. The corresponding
\ absolute address is contained in the ivar dlgPtr.
textH_offs + @ ?dup IF put: teHdl ELSE clear: teHdl THEN ;
:class DIALOG+ super{ dialog }
record
{ ptr F-LINK \ Forward link - ^dlg
ptr B-LINK \ Backward link ditto
bool ENABLED?
ptr PUM-LINK \ Link to any pop-up menus
}
' dlg-chain set_to_class dialog+
' active_dlg set_to_class dialog+
' this_dlg set_to_class dialog+
:m F-LINK: \ ( -- ^dlg )
get: f-link ;m
\ ( ^dlg -- )
:m SET-F-LINK: put: f-link ;m
:m SET-B-LINK: put: b-link ;m
\ ( -- ^dlg )
:m PUM-LINK: get: PUM-link ;m
:m SET-PUM-LINK: put: PUM-link ;m
:m GETNEW:
nil?: dlgPtr 0EXIT \ Out if open already
dlg-chain put: f-link
dlg-chain nilP =
NIF ^base set-b-link: dlg-chain THEN
^base -> dlg-chain clear: b-link
getnew: super
get: dlgPtr set_teHdl
0 -> actW ;m \ Front window is a dialog, not a Mops window
:m CLOSE:
nil?: dlgPtr ?EXIT \ Out if closed already
nil?: f-link
NIF get: b-link get: f-link set-b-link: dialog+ THEN
nil?: b-link
NIF get: f-link get: b-link set-f-link: dialog+
ELSE get: f-link -> dlg-chain
THEN
clear: teHdl nilP -> active_dlg close: super ;m
:m EXEC: \ ( index -- )
get: enabled? if exec: super else drop then ;m
:m ENABLE: true put: enabled? ;m
:m DISABLE: false put: enabled? ;m
:m ENABLED?: get: enabled? ;m
:m CLASSINIT: enable: self ;m
:m DUMP:
^base .h 3 spaces nil?: dlgPtr if ." not " then ." open"
3 spaces get: enabled?
if ." enabled" else ." disabled" then cr
get: f-link ." f-link " .h get: b-link ." b-link " .h
." dlgPtr " get: dlgPtr .h cr
dlg-chain ." dlg-chain " .h ;m
;class
\ =====================================
: FIND-DLG { dlptr -- b }
dlg-chain -> this_dlg
BEGIN
this_dlg nilP = IF false EXIT THEN
dlgPtr: this_dlg dlptr =
IF true EXIT THEN
f-link: this_dlg -> this_dlg
AGAIN ;
: DLGPORT \ Sets the current grafport to the current dialog.
dlgPtr: this_dlg setPort ;
0 value EXEC?
: MLD-EVT
fEvent addr: dptr addr: theItem
DialogSelect 0<> -> exec?
get: dptr find-dlg 0EXIT
exec? 0EXIT
get: theItem 1- exec: this_dlg ;
: CLOSE-DLG \ ( dlptr -- )
find-dlg 0exit
close: this_dlg ;
: IS_DLG_EVT? \ ( -- b )
fevent IsDialogEvent ;
\ ?TEidle calls TEidle if a modeless dialog with a TE field is current.
\ We have to do this at regular intervals in order to get the insertion
\ point to blink. If the call is needed, the handle TEhdl won't be nil,
\ and will be a handle to the TE field. We arrange for this word to be
\ called regularly by having our handler for null events make the call.
: ?TEIDLE
nil?: teHdl ?EXIT
get: teHdl TEidle ;
: UPD-EV appWind? 0EXIT upd-evt ;
: ACTV-EV appWind? 0EXIT actv-evt ;
: NULL-EV ?TEidle null-evt ;
: OS-EV \ When the system sends us Suspend and Resume events, it doesn't
\ deactivate/activate any windows. We have to handle it
\ ourselves. Here we look after non-modal dialog windows.
\ Ordinary windows are handled by OS-EVT in file Event.
OS-evt
suspend?
IF get: TEhdl put: saveTEhdl
nil?: TEhdl
NIF get: TEhdl TEDeactivate clear: TEhdl THEN
EXIT
THEN
resume?
IF get: saveTEhdl put: TEhdl
nil?: TEhdl NIF get: TEhdl TEActivate THEN
THEN ;
: ERR 60 beep abort ;
\ We set the drag limit for dialogs at the time the drag is done - this
\ allows the screen size to change while a dialog is up!
rect DRAG-LIMIT
: SET_DRAG-LIMIT
screenbits put: drag-limit 10 10 inset: drag-limit ;
: ENB? \ ( -- b ) Returns true if WND corresponds to an enabled
\ dialog.
wnd find-dlg NIF false exit THEN
enabled?: this_dlg ;
: ?SELECT \ Selects the dialog corresponding to WND, if enabled.
enb? 0EXIT
wnd SelectWindow ;
: ?DRAG \ Drags the dialog (maybe only if enabled).
enb? 0EXIT \ Include if you don't want disabled dlgs draggable
set_drag-limit
wnd where: fEvent
addr: drag-limit DragWindow ;
: ?CLOSE \ Handles a click in the close box if enabled.
enb? 0EXIT
wnd dup
where: fEvent TrackGoAway
IF close-dlg ELSE drop THEN ;
: MLD-MOUSE-EVT \ ( rgn -- )
\ Handles a click on a dialog window that was not reported
\ as a dialog event. It could be select, drag, grow or close.
\ If the dialog is not enabled, we ignore the click.
SELECT{
3 IS{ ?select }END
4 IS{ ?drag }END
5 IS{ ( A dialog box can't grow! ) }END
6 IS{ ?close }END
DEFAULT{ err
}SELECT ;
: MOUSE-EVT+MLD \ ( -- )
is_dlg_evt? IF MLD-evt EXIT THEN
when: fEvent put: theMouse \ update click interval
where: fEvent find-window -> wnd
wnd windowKind 2 = ( Dialog window? )
IF MLD-mouse-evt
ELSE (mouse-evt)
THEN ;
: KEY-EVT+MLD \ ( -- )
active_dlg nilP =
NIF key: active_dlg 0EXIT \ out if already handled
mods: fEvent $ 100 and
NIF MLD-evt EXIT THEN
THEN
key-evt ;
: UPD-EVT+MLD \ ( -- )
is_dlg_evt?
IF MLD-evt
drawBold: this_dlg EXIT
THEN
msg: fEvent -> wnd
upd-ev ;
: ACTV-EVT+MLD \ ( -- )
msg: fEvent -> wnd
wnd windowKind 2 =
IF mods: fEvent 01 and
IF \ activate
wnd set_TEhdl
msg: fEvent find-dlg
IF this_dlg -> active_dlg
ELSE nilP -> active_dlg
THEN
ELSE \ deactivate
clear: TEhdl nilP -> active_dlg
THEN
is_dlg_evt? IF MLD-evt EXIT THEN
THEN
actv-ev ;
: +MODELESS
XTS{ null-ev mouse-evt+mld null-ev key-evt+mld
null-ev key-evt+mld upd-evt+mld disk-evt
actv-evt+mld null-ev null-ev null-ev
null-ev null-ev null-ev OS-ev
null-ev null-ev null-ev null-ev
null-ev null-ev null-ev HL-evt }
put: fEvent
\ ['] ?TEidle -> TEidle
sleepticks 0< IF 20 ELSE sleepticks 20 min THEN
-> sleepticks ;
endload
\ TESTING:
\ ================== "MLD test" dialog box ==========================
6 dialog+ D1 2 setbold: d1
4 dialog+ D2
: QQQ 20 beep ;
: WWW 1 beep ;
: ZZZ ." useritem hit" cr ;
: USER->TEMPRECT \ ( hdl item# -- b )
swap find-dlg
IF itemHandle: this_dlg drop true
ELSE ( item# ) drop false
THEN ;
PPC?
[IF]
konst uppUserItemProcInfo
:ppc_proc DRAW_USER { -- }
user->tempRect
IF " Hello" tempRect 1 TETextBox
dropShadow: tempRect
THEN
;ppc_proc
[ELSE]
:proc DRAW_USER
user->tempRect
IF " Hello" tempRect 1 TETextBox
dropShadow: tempRect
THEN
;proc
[THEN]
: CLOSE1 close: d1 ;
: CLOSE2 close: d2 ;
XTS{ qqq www close1 togitem zzz zzz } 300 init: d1
XTS{ qqq www close2 zzz } 301 init: d2
: GO
" MLDtest.rsrc" openresfile \ ***
+modeless
getnew: d1 getnew: d2
['] draw_user dup 6 setUserProc: d1 dup 5 setUserProc: d1
4 setUserProc: d2 ;
: zz close: d1 close: d2 -modeless ;